package com.sencorsta.ids.game.world.pak;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sencorsta.ids.common.service.MsgService;
import com.sencorsta.ids.common.service.MysqlService;
import com.sencorsta.ids.common.service.RedisService;
import com.sencorsta.ids.core.log.Out;
import com.sencorsta.ids.game.db.RpMassage;
import com.sencorsta.ids.game.db.SettlementResult;
import com.sencorsta.ids.game.db.Wallet;
import com.sencorsta.ids.game.proto.GamePushRedPackageByProto;
import com.sencorsta.ids.game.proto.GamePushRobMoneyByProto;
import com.sencorsta.ids.game.util.MoneyPiece;
import com.sencorsta.ids.game.util.PacketMoney;
import com.sencorsta.ids.game.util.PushAndSaved;
import com.sencorsta.ids.game.world.bean.Player;
import com.sencorsta.ids.game.world.bean.World;
import com.sencorsta.ids.game.world.room.SaoLeiRoom;
import com.sencorsta.utils.date.DateUtil;
import com.sencorsta.utils.string.StringUtil;
import com.sencorsta.utils.templet.Weights;

import java.util.HashMap;
import java.util.Map;


/**
 * @author TAO
 * @description: 扫雷玩法
 * @date 2019/11/19 22:41
 */
public class SaoLeiPackage extends RedPackage implements RedisService {

    public int thunderNumber;//雷号

    public boolean sgin = true;

    public int mediumMineNumber = 0;//中雷数

    public SaoLeiRoom saoLeiRoom;


    public SaoLeiPackage(String sendUserId, String rpId, int count, long amount, SaoLeiRoom saoLeiRoom, int thunderNumber, long sendDeposit, boolean isRobotPack) {
        super(sendUserId, rpId, count, amount, computeRobDeposit(amount, saoLeiRoom), saoLeiRoom.roomId, isRobotPack);//初始化父类公共属性
        this.thunderNumber = thunderNumber;//初始化雷号

        this.sendDeposit = sendDeposit;//为发包者初始化冻结资金
        this.saoLeiRoom = saoLeiRoom;
        analysis();
    }


    public void update() {
        this.time -= 1;//当前包的时间减1秒
        Out.debug("当前扫雷红包Id==>", rpId, "__房间为==>", saoLeiRoom.roomId, "  count==>", count, "  time==>", time);

        if (status == 0) {
            if (time == 0) {//当前包的死期已到，他妈的干掉
                if (rpResult == null) {//红包结算记录为空，代表
                    Out.debug("当前包无人问津，自动撤回");
                    status = 2;
                    Settlement();//结算
                    return;
                }
                Out.debug("当前包的死期已到，开始清算结果");
                status = 1;
                Settlement();//结算
                return;
            }


            if (count == 0) {//红包抢完了
                Out.debug("当前红包已抢完", "红包Id", rpId);
                status = 1;
                Settlement();//结算
                return;
            }
        }

    }

    @Override
    public void analysis() {
        //判断是否是机器人发包
        boolean isMustWin = World.getInstance().isMustWinbyRoom(roomId);
        int[] weight=new int[]{256,128};
        if (isRobotPack) {//机器人发包
            //机器人发包时 人类必中雷 机器人随便抢
            if (isMustWin) {
                isRobotRobMustWin = true;
                //增加出雷概率
                weight=new int[]{16,256,128,64,32,16,8,4,2};
            }
        } else {//玩家发包
            if (isMustWin) {
                //玩家发包时 如果必赢 机器人只抢赢钱的包 玩家不出雷包
                isRobotRobMustWin = true;
                weight=new int[]{256};
            }

        }
        Weights weights=new Weights(weight);
        this.moneyPieces = PacketMoney.getListAtboom(amount, count, weights.getRandom(),thunderNumber,1);

        for (int i = 0; i < moneyPieces.size(); i++) {
            MoneyPiece jsonObject = moneyPieces.get(i);

            long jMoney = jsonObject.getMoney();
            int jThunderNumber = jsonObject.getThunderNumber();

            int temp = 10000000;
            if (jThunderNumber == thunderNumber) {
                temp *= -1;
            }

            int jScore = (int) (jMoney + temp);
            jsonObject.setScore(jScore);
        }

        for (int j = 0; j < moneyPieces.size(); j++) {
            if (moneyPieces.get(j).getScore() > 0) {
                moneyPieces.get(j).setWin(true);
            } else {
                moneyPieces.get(j).setWin(false);
            }
        }
    }


    //抢红包
    public void rob(Player player) {
        Out.debug("-----------扫雷抢红包--update-----------");

        if (count == 0 || status != 0) {//判断红包数量
            Out.debug("红包已抢完");
            return;
        }

        if (rpResult.containsKey(player.userId)) {
            Out.debug("该红包你以领取过");
            return;
        }


        //不加控制默认
        int index = getNextIndex();
        if (!isRobotPack && player.type == 2 && isRobotRobMustWin) {
            index = getWinIndex();
            if (index < 0) {
                //没有可以用的包了
                return;
            }
        }
        if (isRobotPack&&player.type == 1&&isRobotRobMustWin){
            index = getLoseIndex();
            if (index < 0) {
                //没有可以用的包了
                index=getNextIndex();
            }
        }

        if (count == sumCount && !player.userId.equals(saoLeiRoom.mainUserId)) {//第一个包（房主抢得） 发起抢包者不为房主（不是房主主动抢包）
            if (isRobotRobMustWin) {
                index = getMinScore();
            } else {
                index = getNextIndex();
            }
        }
        playerMap.put(player.userId, player);


        Long robAmount = moneyPieces.get(index).getMoney();//直接将剩余红包金额给最后一个人
        int thunderNumber = moneyPieces.get(index).getThunderNumber();
        moneyPieces.get(index).setRobed(true);

        //将抢的红包和用户对应起来
        JSONObject result = new JSONObject();
        result.put("robUserId", player.userId);
        result.put("amount", robAmount);
        result.put("thunderNumber", thunderNumber);
        result.put("time", DateUtil.getDateTime());
        result.put("nickname", player.nickname);
        result.put("portrait", player.portrait);
        rpResult.put(player.userId, result);

        balance = balance - robAmount;

        //冻结抢包者的最高赔款金额 --防止在抢到红包到结算期间去抢其他红包（最终导致这里的包在结算时余额不够）
        if (!player.userId.equals(saoLeiRoom.mainUserId)) {//房主抢包不扣手续费
            player.onRob(rpId, -robDeposit, robDeposit);
        }

        GamePushRobMoneyByProto.PushRobMoney.Builder push = GamePushRobMoneyByProto.PushRobMoney.newBuilder();
        push.setGameId(World.SAOLEI);
        push.setRoomId(roomId);
        push.setRpId(rpId);
        push.setMoney(robAmount);
        Out.debug("扫雷即将为==》", player.userId, "__推送__");
        if (!StringUtil.isEmpty(player.SID)) {
            MsgService.pushBySID(PushAndSaved.pushProto(player.userId, "push.RobMoney", push), player.SID);
        }

        if (!moneyRecode.containsKey(player.userId)) {//参与抢包用户添加recode的--防止报空
            JSONObject recode = new JSONObject();
            moneyRecode.put(player.userId, recode);
        }
        count = count - 1;
    }


    //通知结算
    public void Settlement() {
        try {
            Out.debug("------------------------扫雷包----rpResult----------------------------");
            Out.debug("扫雷红包详情：", this.toString());
            Out.debug("扫雷红包记录：", rpResult);


            //只有一条结算记录时--并且是房主
            int roomId = saoLeiRoom.roomId;//得到房间ID
            double currentMagnification = saoLeiRoom.magnification;//当前房间倍率
            Map<Long, Long> reward = saoLeiRoom.reward;//得到当前房间的奖励列表


            //不管输赢  把抢的钱给玩家加回去
            long bankWinMoney = 0;
            for (var userId : rpResult.keySet()) {
                JSONObject userRobInfo = (JSONObject) rpResult.get(userId);//得到的userId的结算记录
                int leisureThunderNumber = userRobInfo.getInteger("thunderNumber");//得到当前用户的雷
                long leisureAmount = userRobInfo.getLong("amount");//得到当前用户抢到的钱
                //得到当前玩家的账单
                JSONObject recod = moneyRecode.getJSONObject(userId);
                recod.put("robMoney", leisureAmount);//为当前玩家添加抢的钱的账单


                //中雷情况--结算账单
                if (leisureThunderNumber == thunderNumber && !userId.equals(saoLeiRoom.mainUserId)) {//当前用户中雷  扣钱  排除房主
                    mediumMineNumber = ++mediumMineNumber;//胜利数++
                    long transportAmount = getTransportAmount(currentMagnification);//得到中雷输的钱

                    //2.中雷者扣钱--更改数据库
                    if (userId == saoLeiRoom.mainUserId) {
                        transportAmount = 0;
                    }
                    recod.put("resultMoney", -transportAmount);//为抢包者添加结算的账单
                    bankWinMoney += transportAmount;
                }

                //奖励情况
                if (reward.keySet().size() > 0) {//奖励存在
                    if (reward.containsKey(leisureAmount)) {
                        long rewardAmount = reward.get(leisureAmount);//得到奖励金额
                        //生成得到奖励金玩家的账单
                        recod.put("bonus", rewardAmount);
                        bankWinMoney -= rewardAmount;
                    }
                }
            }


            moneyRecode.getJSONObject(sendUserId).put("sendAmountback", balance);//发包者剩余的钱
            moneyRecode.getJSONObject(sendUserId).put("resultMoney", bankWinMoney);
            JSONArray array = new JSONArray();
            for (String userId : moneyRecode.keySet()) {
                JSONObject resultItem = moneyRecode.getJSONObject(userId);
                long total = 0;
                total += resultItem.getLongValue("sendAmount") + resultItem.getLongValue("sendAmountback") + resultItem.getLongValue("robMoney") + resultItem.getLongValue("resultMoney") + resultItem.getLongValue("bonus");
                long drawWater = getWinAmount(total, playerMap.get(userId));//手续费

                resultItem.put("drawWater", drawWater);

                long totalFreeze = 0;
                long finalMoney = total - drawWater;

                if (userId.equals(sendUserId)) {
                    totalFreeze = sendDeposit;
                } else {
                    totalFreeze = robDeposit;
                }
                resultItem.put("total", finalMoney);

                playerMap.get(userId).onSettlement(rpId, finalMoney + totalFreeze, -totalFreeze);
                array.add(Wallet.addMoneySql(playerMap.get(userId), finalMoney, 0,roomId));
                array.add(SettlementResult.makeResult(this, resultItem, userId, World.SAOLEI));//插入流水账单
            }
            array.add(RpMassage.updateRpMessage(rpId, 2));
            MysqlService.getInstance().executeMultipleAsyn(array);
            Out.debug("扫雷红包详情：", this.toString());
            Out.debug("扫雷红包记录：", rpResult);
            saoLeiRoom.rpPackage.remove(rpId);//内存中移除红包


            GamePushRedPackageByProto.PushRedPackage.Builder push = GamePushRedPackageByProto.PushRedPackage.newBuilder();
            push.setGameId(World.SAOLEI);
            push.setRoomId(roomId);
            push.setRpId(rpId);
            for (Player current : playerMap.values()) {
                if (!current.userId.equals(saoLeiRoom.mainUserId)) {
                    MsgService.pushBySID(PushAndSaved.pushProto(current.userId, "push.RedPackageResult", push), current.SID);
                }

            }

            niuNiuJoinRedis();
            saoLeiRoom.rpPackage.remove(rpId);
        } catch (Exception e) {
            Out.error("扫雷结算报错");
            Out.error(this.toString());
            e.printStackTrace();
        }
    }

    //Redis 红包详情入库
    public void niuNiuJoinRedis() {
        //将红包记录修改到MySql库里

        Map<String, String> rpInfo = new HashMap<>();
        rpInfo.put("sendUserId", sendUserId);//发红包者
        rpInfo.put("gameId", String.valueOf(World.SAOLEI));//游戏Id
        rpInfo.put("roomId", String.valueOf(roomId));//房间Id
        rpInfo.put("thunderNumber", String.valueOf(thunderNumber));//雷号
        rpInfo.put("RpId", rpId);//红包ID
        rpInfo.put("count", String.valueOf(count));//红包余数
        rpInfo.put("sumCount", String.valueOf(sumCount));//红包总个数
        rpInfo.put("amount", String.valueOf(amount));//红包金额
        rpInfo.put("balance", String.valueOf(balance));//红包余额
        rpInfo.put("moneyPieces", JSON.toJSONString(moneyPieces));//金额分配
        rpInfo.put("rpResult", String.valueOf(rpResult));//红包结果
        rpInfo.put("time", String.valueOf(time));//红包时间
        rpInfo.put("status", String.valueOf(status));//红包状态  0:发出 1:完成  2.撤回
        rpInfo.put("robDeposit", String.valueOf(robDeposit));//押金
        rpInfo.put("mediumMineNumber", String.valueOf(mediumMineNumber));//中雷数
        R_REDPACKAGE_INFO.hmset(rpId, rpInfo);
    }


    //得到抢红包的人的押金multiplyingPower
    public static long computeRobDeposit(long amount, SaoLeiRoom saoLeiRoom) {
        return (long) (amount * saoLeiRoom.magnification);//为押金赋值
    }


    //得到输的金额
    public long getTransportAmount(double currentMagnification) {
        //赢的金额 = 抢到的金额 * 牛数倍率
        return (long) (amount * currentMagnification);
    }

}
